{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Matplotlib: treemap\n",
    "======================================================================\n",
    "\n",
    "Treemaps are a nice way of showing tree information not based on a\n",
    "connected node approach.\n",
    "\n",
    "See <http://www.cs.umd.edu/hcil/treemap/>\n",
    "\n",
    "![](files/attachments/Matplotlib_TreeMap/TreeMap.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Treemap builder using pylab.\n",
    "\n",
    "Uses algorithm straight from http://hcil.cs.umd.edu/trs/91-03/91-03.html\n",
    "\n",
    "James Casbon 29/7/2006\n",
    "\"\"\"\n",
    "\n",
    "import pylab\n",
    "from matplotlib.patches import Rectangle\n",
    "\n",
    "class Treemap:\n",
    "    def __init__(self, tree, iter_method, size_method, color_method):\n",
    "        \"\"\"create a tree map from tree, using itermethod(node) to walk tree,\n",
    "        size_method(node) to get object size and color_method(node) to get its \n",
    "        color\"\"\"\n",
    "\n",
    "        self.ax = pylab.subplot(111,aspect='equal')\n",
    "        pylab.subplots_adjust(left=0, right=1, top=1, bottom=0)\n",
    "        self.ax.set_xticks([])\n",
    "        self.ax.set_yticks([])\n",
    "\n",
    "        self.size_method = size_method\n",
    "        self.iter_method = iter_method\n",
    "        self.color_method = color_method\n",
    "        self.addnode(tree)\n",
    "\n",
    "    def addnode(self, node, lower=[0,0], upper=[1,1], axis=0):\n",
    "        axis = axis % 2\n",
    "        self.draw_rectangle(lower, upper, node)\n",
    "        width = upper[axis] - lower[axis]\n",
    "        try:\n",
    "            for child in self.iter_method(node):\n",
    "                upper[axis] = lower[axis] + (width * float(self.size_method(child))) / self.size_method(node)\n",
    "                self.addnode(child, list(lower), list(upper), axis + 1)\n",
    "                lower[axis] = upper[axis]\n",
    "\n",
    "        except TypeError:\n",
    "            pass\n",
    "\n",
    "    def draw_rectangle(self, lower, upper, node):\n",
    "        print lower, upper\n",
    "        r = Rectangle( lower, upper[0]-lower[0], upper[1] - lower[1],\n",
    "                   edgecolor='k',\n",
    "                   facecolor= self.color_method(node))\n",
    "        self.ax.add_patch(r)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    # example using nested lists, iter to walk and random colors\n",
    "\n",
    "    size_cache = {}\n",
    "    def size(thing):\n",
    "        if isinstance(thing, int):\n",
    "            return thing\n",
    "        if thing in size_cache:\n",
    "            return size_cache[thing]\n",
    "        else:\n",
    "            size_cache[thing] = reduce(int.__add__, [size(x) for x in thing])\n",
    "            return size_cache[thing]\n",
    "    import random\n",
    "    def random_color(thing):\n",
    "        return (random.random(),random.random(),random.random())\n",
    "\n",
    "    tree= ((5,(3,5)), 4, (5,2,(2,3,(3,2,2)),(3,3)), (3,2) )\n",
    "\n",
    "    Treemap(tree, iter, size, random_color)\n",
    "    pylab.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
